﻿function HasSeasonSubDirs([string] $a) {
    $ainfo = New-Object system.IO.DirectoryInfo $a
    return ($ainfo.GetDirectories("s??").Count -gt 0) -or ($ainfo.GetDirectories("????").Count -gt 0)
}

function MovePath([string] $src, [string] $dst, [bool] $force) {
    $sourceFound = Test-Path $src
    $targetFound = Test-Path $dst
    if ($sourceFound -and $targetFound) {
        $nsd = !(HasSeasonSubDirs $dst)
        if ($nsd -or $force) {
            $textColor = if ($global_mode -eq "or") {"blue"} else {"green"}
            Write-Host "    Moving '" -nonewline; Write-Host "$src" -f $textColor -nonewline
            Write-Host "' to '$dst' ..."
            Move-Item -path $src -destination "$dst"
        }
        if (!$nsd -and !$force) {
            Write-Host ">>> Skipping moving '$src' to '$dst' since there are subdirs!" -f red
        }
    }
    if (!$targetFound) {
        Write-Host ">>> Target folder '$dst' not found!" -f red
    }
}

function MoveRelease([string] $rel, [string] $dst, [bool] $force = $false) {
    if      ($dst -like "_various*")    {$dst_drive = "t"}
    elseif  ($dst -like "0123456789\*") {$dst_drive = "t"}
    elseif  ($dst -like "abcde\*")      {$dst_drive = "t"}
    elseif  ($dst -like "fghij\*")      {$dst_drive = "t"}
    elseif  ($dst -like "klmno\*")      {$dst_drive = "t"}
    elseif  ($dst -like "pqrst\*")      {$dst_drive = "t"}
    elseif  ($dst -like "uvwxy\*")      {$dst_drive = "t"}
    elseif  ($dst -like "zaao\*")       {$dst_drive = "t"}
    else { Throw "Bad destination!"}
    $dstPath = Join-Path ($dst_drive + ":\dc\share\tv_series") $dst
    MovePath $rel $dstPath $force
}

function MoveUnpacked([string] $f, [string] $category, [string] $dst, [bool] $force) {
    switch ($category) { 
        Facts   {$preDst = "w:\fakta & natur"} 
        Humor   {$preDst = "w:\humor"} 
        Music   {$preDst = "v:\musik"} 
        Sport   {$preDst = "w:\sport"} 
        Tv      {$preDst = "w:\tv-serier"} 
        default {Throw "Bad category!"}
    }
    MovePath $f (Join-Path $preDst $dst) $force
}

function MoveTv([string] $rel, [string] $dst_or, 
                [string] $dst_tv_category, [string] $dst_tv, 
                [bool] $force = $false, [bool] $prefix_episode = $false) {

    # Use regex to handle all season parts of name etc
    $se_regex = $rel -replace ".%s", "\.S(\d{2})E(\d{2}).*"
    $se_regex_valid = $rel -ne $se_regex
    $sf_regex = $rel -replace ".%s", "\.(\d)x(\d{2})\..*"
    $sf_regex_valid = $rel -ne $sf_regex
    $sp_regex = $rel -replace ".%s", "\.S(\d{2})\..*"
    $sp_regex_valid = $rel -ne $sp_regex
    $y_regex = $rel -replace ".%y", "\.(\d{4})\..*"
    $y_regex_valid = $rel -ne $y_regex
    $e_regex = $rel -replace ".%e", "\.E\d{2}\..*"
    $e_regex_valid = $rel -ne $e_regex
    $items_tv = Get-ChildItem $PSScriptRoot | where {! $_.PSIsContainer}
    $items_or = Get-ChildItem $PSScriptRoot | where {$_.PSIsContainer}
    $items = if ($global_mode -eq "or") {$items_or} else {$items_tv}
    ForEach ($item in $items) {
        $src = ""
        $dst_add = ""
        $episode = ""
        if (($se_regex_valid) -and ($item -match $se_regex)) {
            $season = $matches[1]
            $episode = $matches[2]
            $rel_base = $rel -replace "\.%s", ""
            $src = $rel_base + ".S" + $season + "E" + $episode + "*"
            $dst_add = "\s" + $season
        }
        elseif (($sf_regex_valid) -and ($item -match $sf_regex)) {
            $season = $matches[1]
            $episode = $matches[2]
            $rel_base = ($rel -replace "\.%s", "") -replace "\.", "_"
            $src = $rel_base + "." + $season + "x" + $episode + ".*"
            $dst_add = "\s0" + $season
        }
        elseif (($sp_regex_valid) -and ($item -match $sp_regex)) {
            $season = $matches[1]
            $rel_base = $rel -replace "\.%s", ""
            $src = $rel_base + "." + $season + ".*"
            $dst_add = "\s" + $season
        }
        elseif (($y_regex_valid) -and ($item -match $y_regex)) {
            $year = $matches[1]
            $rel_base = $rel -replace "\.%y", ""
            $src = $rel_base + "." + $year + ".*"
            $dst_add = "\" + $year
        }
        elseif (($e_regex_valid) -and ($item -match $e_regex)) {
            $src = $rel -replace "\.%e", ".E*"
            $dst_add = "\s01"
        }
        elseif ($rel -match ".*\*") {
            $rel_regex = $rel -replace "\*", ".*" # Cheap convertion of glob to regex (good enough)
            if ($item -match $rel_regex) {
                $src = $rel
            }
        }
        else {
            # Write-Host "    '$item' doesn't match '$rel'..."
        }
        if (($global_mode -eq "tv") -and $prefix_episode -and $episode) {
            $items = Get-ChildItem $PSScriptRoot | where {
                (! $_.PSIsContainer) -and ($_ -match $src)
            }
            ForEach ($item in $items) {
                $item_path = Join-Path $PSScriptRoot $item
                $item_new_name = $episode + "_" + $item
                Rename-Item -Path $item_path -NewName $item_new_name
            }
            $src = $episode + "_" + $src
        }
        if ($src) {
            if (($global_mode -eq "or") -and (Test-Path $src -pathType Container)) {
                MoveRelease $src ($dst_or + $dst_add) $force
            }
            elseif (($global_mode -eq "tv") -and (Test-Path $src -pathType Leaf)) {
                MoveUnpacked $src $dst_tv_category ($dst_tv + $dst_add) $force
            }
        }
    }
}

#--------------------------------------------------------------------
$getPathNameSignature = @'
[DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Auto)]
public static extern uint GetLongPathName(
    string shortPath, 
    StringBuilder sb, 
    int bufferSize);

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError=true)]
public static extern uint GetShortPathName(
   string longPath,
   StringBuilder shortPath,
   uint bufferSize);
'@
$getPathNameType = Add-Type -MemberDefinition $getPathNameSignature -Name GetPathNameType -UsingNamespace System.Text -PassThru
function Get-PathCanonicalCase
{
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true)]
        [string]
        # Gets the real case of a path
        $Path
    )

    if( -not (Test-Path $Path) )
    {
        Write-Error "Path '$Path' doesn't exist."
        return
    }

    $shortBuffer = New-Object Text.StringBuilder ($Path.Length * 2)
    [void] $getPathNameType::GetShortPathName( $Path, $shortBuffer, $shortBuffer.Capacity )

    $longBuffer = New-Object Text.StringBuilder ($Path.Length * 2)
    [void] $getPathNameType::GetLongPathName( $shortBuffer.ToString(), $longBuffer, $longBuffer.Capacity )

    return $longBuffer.ToString()
}
